﻿using Modbus.Device;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Net.Security;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading.Tasks;


namespace Equipment
{
    public sealed class ATEQ620
    {
        private static readonly ATEQ620 _instance = new ATEQ620();


        private ATEQ620()
        {
            Port = new SerialPort();
        }

        public static ATEQ620 Instance
        {
            get
            { return _instance; }
        }

        public SerialPort Port { get; set; }


        public void Initialize(string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits, byte slaveId)
        {
            Port.PortName = portName;
            Port.BaudRate = baudRate;
            Port.Parity = parity;
            Port.DataBits = dataBits;
            Port.StopBits = stopBits;
            _slaveId = slaveId;

            if (!Port.IsOpen)
            {
                Port.Open();
            }
            Master = ModbusSerialMaster.CreateRtu(Port);
            Master.Transport.ReadTimeout = 1000;
            

        }
        public IModbusMaster Master { get; set; }

        private byte _slaveId { get; set; }

        public ushort[] ReadNWord(ushort address, ushort numofpoints)
        {
            return Master.ReadHoldingRegisters(_slaveId, address, numofpoints);
        }

        public void WriteNWord(ushort address, ushort[] data)
        {
            Master.WriteMultipleRegisters(_slaveId, address, data);
        }
        public void Writebit(ushort address,bool flag)
        {
            Master.WriteSingleCoil(_slaveId, address, flag);
        }

        public void Reset()
        {
            Master.WriteSingleCoil(_slaveId, 0x0, true);
        }
        public void Start()
        {
            Master.WriteSingleCoil(_slaveId, 0x01, true);
        }

        public void Stop()
        {
            Master.WriteSingleCoil(_slaveId,0x02, true);  
        }
        public async Task ResetAsync()
        {
            await Master.WriteSingleCoilAsync(_slaveId, 0, true);
        }

        public async Task StartAsync()
        {
            await Master.WriteSingleCoilAsync(_slaveId, 0x01, true);
        }
        public async Task StopAsync()
        {
            await Master.WriteSingleCoilAsync(_slaveId, 0x02, true);
        }

        public LiveData LiveDataRead()
        {
            LiveData result;
            ushort[] data= new ushort[13];
            data =Master.ReadHoldingRegisters(_slaveId, 0x30, 0x0D);
            result.ProgramNumber = data[0];
            result.NumberofResults = data[1];
            result.TestType = data[2];
            result.RelaysImage = data[3];
            result.StepCode = data[4];
            result.PressureValue = Joint(data[5],data[6]);
            result.PressureUnitCode = Joint(data[7],data[8]);
            result.LeakValue = Joint(data[9],data[10]);
            result.LeakUnitCode =Joint(data[11],data[12]);
                       
            return result;
        }
        
        public void ChangeProgram(ushort  programnumber)
        {
            ushort[] data = new ushort[1];
            data[0] = (ushort)(programnumber - 1);
            Master.WriteMultipleRegisters(_slaveId, 0x200, data);
        }

        public int Joint(ushort x, ushort y)
        {
            
            return System.Net.IPAddress.HostToNetworkOrder(x << 16 | y);
        }
    }

    public struct LiveData
    {
        public ushort ProgramNumber;
        public ushort NumberofResults;
        public ushort TestType;
        public ushort RelaysImage;
        public ushort StepCode;
        public int PressureValue;
        public int PressureUnitCode;
        public int LeakValue;
        public int LeakUnitCode;
    }
    public struct ResultData
    {
        public ushort ProgramNumber;
        public ushort TestType;
        public ushort RelaysImage;
        public ushort AlarmCode;
        public int PressureValue;
        public int PressureUnitCode;
        public int LeakValue;
        public int LeakUnitCode;
    }
}
